using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using AutoMapper;
using MediatR;
using Microsoft.EntityFrameworkCore;
using Microsoft.IdentityModel.Tokens;
using WMS.Api.Application.Commands;
using WMS.Common;
using WMS.Domain;
using WMS.Infrastructure;

namespace WMS.Api.Application.CommandHandlers
{
    /// <summary>
    /// 用户登录命令处理程序
    /// </summary>
    public class UserLoginCommandHandler : IRequestHandler<UserLoginCommand, ApiResult<UserLoginResponseDto>>
    {
        private readonly IBaseRepository<UserInfo> _userRepository;
        private readonly IBaseRepository<RoleUser> _roleUserRepository;
        private readonly IBaseRepository<Role> _roleRepository;
        private readonly IBaseRepository<RolePermission> _rolePermissionRepository;
        private readonly IBaseRepository<Permission> _permissionRepository;
        private readonly IConfiguration _configuration;
        private readonly IMapper _mapper;
        private readonly ILogger<UserLoginCommandHandler> _logger;

        public UserLoginCommandHandler(
            IBaseRepository<UserInfo> userRepository,
            IBaseRepository<RoleUser> roleUserRepository,
            IBaseRepository<Role> roleRepository,
            IBaseRepository<RolePermission> rolePermissionRepository,
            IBaseRepository<Permission> permissionRepository,
            IConfiguration configuration,
            IMapper mapper,
            ILogger<UserLoginCommandHandler> logger)
        {
            _userRepository = userRepository;
            _roleUserRepository = roleUserRepository;
            _roleRepository = roleRepository;
            _rolePermissionRepository = rolePermissionRepository;
            _permissionRepository = permissionRepository;
            _configuration = configuration;
            _mapper = mapper;
            _logger = logger;
        }

        public async Task<ApiResult<UserLoginResponseDto>> Handle(UserLoginCommand request, CancellationToken cancellationToken)
        {
            var result = new ApiResult<UserLoginResponseDto>("用户登录");

            try
            {
                // 查询用户
                var user = await _userRepository.GetNewValueAsync(u => u.LoginName == request.LoginName && !u.IsDel);

                // 用户不存在
                if (user == null)
                {
                    result.code = StatusCodeEnum.DataNotExist;
                    result.msg = "用户名或密码错误";
                    return result;
                }

                // 检查用户是否被锁定
                if (user.IsLock)
                {
                    result.code = StatusCodeEnum.UserDisable;
                    result.msg = "账号已被锁定，请联系管理员";
                    return result;
                }

                // 验证密码
                if (user.Password != request.LoginPwd)
                {
                    // 密码错误，增加错误次数
                    user.ErrorCount++;
                    
                    // 错误次数达到3次，锁定账户
                    if (user.ErrorCount >= 3)
                    {
                        user.IsLock = true;
                        await _userRepository.UpdateNewAsync(user);
                        
                        result.code = StatusCodeEnum.UserDisable;
                        result.msg = "密码错误次数过多，账号已被锁定";
                        return result;
                    }
                    
                    // 更新错误次数
                    await _userRepository.UpdateNewAsync(user);
                    
                    result.code = StatusCodeEnum.Fail;
                    result.msg = $"用户名或密码错误，还剩{3 - user.ErrorCount}次机会";
                    return result;
                }

                // 登录成功，重置错误次数
                user.ErrorCount = 0;
                await _userRepository.UpdateNewAsync(user);

                // 获取用户角色
                var roleUsers = await _roleUserRepository.GetAllAsync(ru => ru.UserId == user.UserId);
                var roleIds = roleUsers.Select(ru => ru.RId).ToList();
                
                // 获取角色信息
                var roles = await _roleRepository.GetAllAsync(r => roleIds.Contains(r.Id) && !r.IsDeleted);
                var roleNames = roles.Select(r => r.RoleName).ToList();
                
                // 获取权限信息
                var rolePermissions = await _rolePermissionRepository.GetAllAsync(rp => roleIds.Contains(rp.RId));
                var permissionIds = rolePermissions.Select(rp => rp.PerId).Distinct().ToList();
                var permissions = await _permissionRepository.GetAllAsync(p => permissionIds.Contains(p.Pid) && !p.IsDel);
                var permissionCodes = permissions.Select(p => p.RoutePath).ToList();

                // 生成Token
                var token = GenerateJwtToken(user, roleNames);

                // 构造返回结果
                var userDto = new UserLoginResponseDto
                {
                    UserId = user.UserId,
                    UserName = user.UserName,
                    LoginName = user.LoginName,
                    Gender = user.Gender ? "男" : "女",
                    Phone = user.Phone,
                    RoleIds = roleIds,
                    RoleNames = roleNames,
                    Permissions = permissionCodes,
                    Token = token
                };

                result.Success(userDto);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "用户登录失败");
                result.code = StatusCodeEnum.Fail;
                result.msg = $"登录失败：{ex.Message}";
            }

            return result;
        }

        /// <summary>
        /// 生成JWT令牌
        /// </summary>
        /// <param name="user">用户信息</param>
        /// <param name="roleNames">角色名称列表</param>
        /// <returns>JWT令牌</returns>
        private string GenerateJwtToken(UserInfo user, List<string> roleNames)
        {
            var claims = new List<Claim>
            {
                new Claim(JwtRegisteredClaimNames.Sub, user.UserId.ToString()),
                new Claim(JwtRegisteredClaimNames.Name, user.UserName),
                new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
                new Claim("LoginName", user.LoginName)
            };

            // 添加角色声明
            foreach (var roleName in roleNames)
            {
                claims.Add(new Claim(ClaimTypes.Role, roleName));
            }

            var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["Jwt:Key"] ?? "kdsfldsflkdslkflkdsflkdslfdslkflk"));
            var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
            var expires = DateTime.Now.AddHours(Convert.ToDouble(_configuration["Jwt:ExpireHours"] ?? "24"));

            var token = new JwtSecurityToken(
                issuer: _configuration["Jwt:Issuer"] ?? "BeiJingBW",
                audience: _configuration["Jwt:Audience"] ?? "BeiJingBW",
                claims: claims,
                expires: expires,
                signingCredentials: creds
            );

            return new JwtSecurityTokenHandler().WriteToken(token);
        }
    }
} 